<?php

namespace Hilaoyu\LaravelExtend\Supports;
/**
 * Created by laoyu.
 * User: hilaoyu@qq.com
 * Date: 2018/9/27
 * Time: 10:20
 */


use Hilaoyu\Utils\UtilStr;
use Illuminate\Config\Repository;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Str;

class SubApp
{
    static public function register($path, $namespace, $config_replaces = [], $route_config = [])
    {
        //dump($path);

        static::registerExtendConfig($path, $config_replaces);
        static::registerProviders($path);
        if (!app()->runningInConsole()) {
            static::registerRoutes($path . '/routes', $namespace . '\\Controllers', $route_config);
        }

        static::registerCommands($path . '/Commands', $namespace . '\\Commands');

    }

    static public function replaceConfig($config, $config_replaces = [])
    {
        $need_json_de = false;
        if (!is_string($config)) {
            $config = json_encode($config);
            $need_json_de = true;
        }

        /*$preg_replaces = [] ;
        if (is_array($config_replaces) && !empty($config_replaces)) {

            foreach ($config_replaces as $key => $value) {

                $preg_replaces['/'. $key .'/u'] = function ($match) use ($value) {
                    if($value instanceof \Closure){
                        $value = call_user_func($value,$match[0]);
                    }else{
                        $value = (string)$value;
                    }
                    return $value;
                };

                //$config = str_replace($key, $value, $config);
            }

            $config = preg_replace_callback_array($preg_replaces,$config);
        }*/

        $config = UtilStr::replace($config, $config_replaces);


        if ($need_json_de) {
            $config = json_decode($config, true);
        }

        return $config;

    }

    static public function registerExtendConfig($path, $config_replaces = [], $return_only = false)
    {

        $extend_config_file = $path . '/config.php';

        $config_rep = new Repository();

        if (file_exists($extend_config_file)) {
            $extend_config = include($extend_config_file);

            if ($extend_config = static::replaceConfig($extend_config, $config_replaces)) {
                foreach ($extend_config as $key => $config) {
                    $config_rep->set($key, $config);
                    if (!$return_only) {

                        config()->set($key, $config);
                    }
                }
            }
            //dd($config);
        }
        return $config_rep;
    }

    static public function registerProviders($path)
    {
        $providers_config_file = $path . '/providers.php';
        if (file_exists($providers_config_file)) {
            $providers = include($providers_config_file);

            foreach ((array)$providers as $provider) {
                app()->register($provider);
            }
        }

    }
    static public function registerGlobalFunction($path)
    {
        $functions_file = $path . '/functions.php';
        if (file_exists($functions_file)) {
            include_once($functions_file) ;
        }

    }

    static public function registerRoutes($path, $namespace = '', $route_config = [], $type = '')
    {



        $type = trim($type);
        $prefix = data_get($route_config, 'prefix', '');
        $name = data_get($route_config, 'name', '');
        $domain = data_get($route_config, 'domain', null);
        $middleware = (array)data_get($route_config, 'middleware', []);
        $middleware_web = (array)data_get($route_config, 'middleware_web', []);
        $middleware_api = (array)data_get($route_config, 'middleware_api', []);

        $middleware_web = array_merge(['web'], $middleware, $middleware_web);
        $middleware_api = array_merge(['api'], $middleware, $middleware_api);


        $prefix = trim($prefix);
        $name = trim($name);
        $prefix_api = $prefix ? ($prefix . '/api') : 'api';

        $web_route_files = [];
        $api_route_files = [];

        $appRouter = app('router')
            ->domain($domain)
            ->namespace($namespace)
        ;


        if (is_callable($path)) {
            $appRouter->prefix($prefix)
                ->name($type.'.'.$name)
                ->middleware($middleware)
                ->group($path);
        }else{
            if (!file_exists($path)) {
                return false;
            }
            if (is_dir($path)) {
                $web_route_files = glob($path . '/web.*.php');
                $api_route_files = glob($path . '/api.*.php');
            } elseif (is_file($path)) {
                if ('' == $type) {
                    $type = UtilStr::substr(basename($path), 0, 3);
                }
                if ('web' == $type) {
                    $web_route_files[] = $path;
                } elseif ('api' == $type) {
                    $api_route_files[] = $path;
                }
            }

            foreach ($web_route_files as $file) {

                $appRouter->prefix($prefix)
                    ->name('web.' . $name)
                    ->middleware($middleware_web)
                    ->group($file);
            }


            foreach ($api_route_files as $file) {

                $appRouter->prefix($prefix_api)
                    ->name('api.' . $name)
                    ->middleware($middleware_api)
                    ->group($file);
            }
        }



        if (!app()->isBooted()) {
            app('router')->getRoutes()->refreshNameLookups();
            app('router')->getRoutes()->refreshActionLookups();
        }

        return true;
    }


    static public function registerCommands($path, $namespace = '')
    {
        if (!file_exists($path)) {
            return false;
        }
        $app = app();
        //$namespace = app()->getNamespace();
        $namespace = Str::finish($namespace, '\\');
        try {
            $command_files = [];
            if (is_dir($path)) {
                $command_files = glob($path . DIRECTORY_SEPARATOR . '*.php');
            } elseif (is_file($path)) {
                $command_files[] = $path;
            }


            foreach ($command_files as $file) {

                $command = $namespace . str_replace(
                        ['/', '.php'],
                        ['\\', ''],
                        Str::after($file, $path . DIRECTORY_SEPARATOR)
                    );

                if (is_subclass_of($command, Command::class) &&
                    !(new \ReflectionClass($command))->isAbstract()
                ) {


                    if ($command = app()->make($command)) {
                        if (!$app->isBooted()) {
                            \Illuminate\Console\Application::starting(function ($artisan) use ($command) {
                                //dd(get_class($artisan->getDefinition()));
                                $artisan->add($command);
                            });
                        } else {
                            Artisan::registerCommand($command);
                        }
                        /*\Illuminate\Console\Application::starting(function ($artisan) use ($command) {
                            //dd(get_class($artisan->getDefinition()));
                            $artisan->add($command);
                        });*/
                        /*if(app()->runningInConsole()){
                            Artisan::registerCommand($command);
                        }else{
                            \Illuminate\Console\Application::starting(function ($artisan) use ($command) {
                                //dd(get_class($artisan->getDefinition()));
                                $artisan->add($command);
                            });
                        }*/
                    }


                }

            }
        } catch (\Exception $e) {
            //dump($e->getMessage());
        }

        return true;
    }


}
